using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace MapEditor
{
    //Declare a state enum
    public enum State
    {
        PLAY,
        FREEZE
    }
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        //Declare the state of the application
        public static State state = State.PLAY;

        public static GraphicsDeviceManager graphics;
        public static SpriteBatch spriteBatch;

        //Declare the client bounds
        public static Vector2 clientBounds;

        //Declare Globals
        public static bool quit = false;
        public static Vector2 drawOffset = Vector2.Zero;

        //Declare File Names
        public static String mapName;
        public static String fileName;
        public static String loadFileName;
        public static String Front1tileSheetFileName;
        public static String Front2tileSheetFileName;
        public static String Front3tileSheetFileName;
        public static String PlayertileSheetFileName;
        public static String EnemytileSheetFileName;
        public static String ScreentileSheetFileName;
        public static String Back1tileSheetFileName;
        public static String Back2tileSheetFileName;
        public static String Back3tileSheetFileName;

        //Declare a var to hold the drawable layer
        public static int drawableLayer = 0;

        //Declare a map
        public static Map_Classes.Map map;

        //Declare map and tile dimensions
        public static int FrontLayer1Width = 15;
        public static int FrontLayer1Height = 20;
        public static int Front1TileWidth = 32;
        public static int Front1TileHeight = 32;
        public static int Front1LayerType = 0;
        public static bool Front1Draw = true;
        public static Texture2D Front1TileSheet;

        public static int FrontLayer2Width = 15;
        public static int FrontLayer2Height = 20;
        public static int Front2TileWidth = 32;
        public static int Front2TileHeight = 32;
        public static int Front2LayerType = 0;
        public static bool Front2Draw = true;
        public static Texture2D Front2TileSheet;

        public static int FrontLayer3Width = 15;
        public static int FrontLayer3Height = 20;
        public static int Front3TileWidth = 32;
        public static int Front3TileHeight = 32;
        public static int Front3LayerType = 0;
        public static bool Front3Draw = true;
        public static Texture2D Front3TileSheet;

        public static int ScreenLayerWidth = 15;
        public static int ScreenLayerHeight = 20;
        public static int ScreenTileWidth = 32;
        public static int ScreenTileHeight = 32;
        public static int ScreenLayerType = 0;
        public static bool ScreenDraw = true;
        public static Texture2D ScreenTileSheet;

        public static int PlayerLayerWidth = 15;
        public static int PlayerLayerHeight = 20;
        public static int PlayerTileWidth = 32;
        public static int PlayerTileHeight = 32;
        public static int PlayerLayerType = 0;
        public static bool PlayerDraw = true;
        public static Texture2D PlayerTileSheet;

        public static int EnemyLayerWidth = 15;
        public static int EnemyLayerHeight = 20;
        public static int EnemyTileWidth = 32;
        public static int EnemyTileHeight = 32;
        public static int EnemyLayerType = 0;
        public static bool EnemyDraw = true;
        public static Texture2D EnemyTileSheet;

        public static int BackgroundLayer1Width = 15;
        public static int BackgroundLayer1Height = 20;
        public static int Back1TileWidth = 32;
        public static int Back1TileHeight = 32;
        public static int Back1LayerType = 0;
        public static bool Back1Draw = true;
        public static Texture2D Back1TileSheet;

        public static int BackgroundLayer2Width = 15;
        public static int BackgroundLayer2Height = 20;
        public static int Back2TileWidth = 32;
        public static int Back2TileHeight = 32;
        public static int Back2LayerType = 0;
        public static bool Back2Draw = true;
        public static Texture2D Back2TileSheet;

        public static int BackgroundLayer3Width = 15;
        public static int BackgroundLayer3Height = 20;
        public static int Back3TileWidth = 32;
        public static int Back3TileHeight = 32;
        public static int Back3LayerType = 0;
        public static bool Back3Draw = true;
        public static Texture2D Back3TileSheet;

        public static bool SpacePressed = false;

        //Declare the selected tile
        public static int selectedTileNo = 0;

        public static Texture2D tileSheet;
        public static Texture2D solid;
        Texture2D pixel;

        //Declare inpust states
        MouseState curState;
        KeyboardState prevState;

        //Declare a font
        SpriteFont basic;

        //Declare the GUI
        GUI.HUD hud;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            //Initialize the map
            map = new Map_Classes.Map(FrontLayer1Height, FrontLayer1Width, Front1TileHeight, Front1TileWidth, Front1LayerType, FrontLayer2Height, FrontLayer2Width, Front2TileHeight, Front2TileWidth, Front2LayerType, FrontLayer3Height, FrontLayer3Width, Front3TileHeight, Front3TileWidth, Front3LayerType,
                ScreenLayerHeight, ScreenLayerWidth, ScreenTileHeight, ScreenTileWidth, ScreenLayerType, PlayerLayerHeight, PlayerLayerWidth, PlayerTileHeight, PlayerTileWidth, PlayerLayerType, EnemyLayerHeight, EnemyLayerWidth, EnemyTileHeight, EnemyTileWidth, EnemyLayerType, BackgroundLayer1Height,
                BackgroundLayer1Width, Back1TileHeight, Back1TileWidth, Back1LayerType, BackgroundLayer2Height, BackgroundLayer2Width, Back2TileHeight, Back2TileWidth, Back2LayerType, BackgroundLayer3Height, BackgroundLayer3Width, Back3TileHeight, Back3TileWidth, Back3LayerType);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            //Make Mouse Visible and change window dimensions
            this.IsMouseVisible = true;

            //Set the window size
            graphics.PreferredBackBufferHeight = 700;
            graphics.PreferredBackBufferWidth = 800;
            graphics.ApplyChanges();

            drawOffset.X = 0;
            drawOffset.Y = 0;

            //Initialize the client bounds
            clientBounds = new Vector2(Window.ClientBounds.Width, Window.ClientBounds.Height);


            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //Load textures
            pixel = Content.Load<Texture2D>(@"Sprites/pixel");
            solid = Content.Load<Texture2D>(@"Sprites/solid");

            //Load the sprite font
            basic = Content.Load<SpriteFont>(@"Basic");


            //Initialize the HUD
            hud = new MapEditor.GUI.HUD(Content);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (quit)
                this.Exit();

            //Update the map title
            this.Window.Title = "Map Editor  -  " + mapName;

            //Update selected tile
            KeyboardState keyState = Keyboard.GetState();
            if (selectedTileNo < map.tileSet.Count - 1)
            {
                if (keyState.IsKeyDown(Keys.Up) && !prevState.IsKeyDown(Keys.Up))
                    selectedTileNo++;
            }
            if(selectedTileNo > 0)
            {
                if (keyState.IsKeyDown(Keys.Down) && !prevState.IsKeyDown(Keys.Down))
                    selectedTileNo--;
            }
            if (Game1.Front1tileSheetFileName != null && Game1.Front2tileSheetFileName != null && Game1.Front3tileSheetFileName != null && Game1.PlayertileSheetFileName != null && Game1.EnemytileSheetFileName != null && Game1.ScreentileSheetFileName != null && Game1.Back1tileSheetFileName != null && Game1.Back2tileSheetFileName != null && Game1.Back3tileSheetFileName != null)
            {
                if (keyState.IsKeyDown(Keys.Space))
                {
                    SpacePressed = true;
                }
            }

            if (SpacePressed == true)
            {
                KeyboardState keyState2 = Keyboard.GetState();

                if (keyState2.IsKeyUp(Keys.Space))
                {
                    SpacePressed = false;
                    if (Game1.Front1tileSheetFileName != null && Game1.Front2tileSheetFileName != null && Game1.Front3tileSheetFileName != null && Game1.PlayertileSheetFileName != null && Game1.EnemytileSheetFileName != null && Game1.ScreentileSheetFileName != null && Game1.Back1tileSheetFileName != null && Game1.Back2tileSheetFileName != null && Game1.Back3tileSheetFileName != null)
                    {
                        state = State.FREEZE;

                        Forms.Tiles TileForm = new Forms.Tiles();
                        TileForm.ShowDialog();

                        if (TileForm.DialogResult == System.Windows.Forms.DialogResult.OK)
                        {
                            selectedTileNo = TileForm.TileClicked;
                        }

                        state = State.PLAY;
                    }                 
                    
                }
                
            }

            //Get input from the mouse
            if (state == State.PLAY && Game1.Front1tileSheetFileName != null && Game1.Front2tileSheetFileName != null && Game1.Front3tileSheetFileName != null && Game1.PlayertileSheetFileName != null && Game1.EnemytileSheetFileName != null && Game1.ScreentileSheetFileName != null && Game1.Back1tileSheetFileName != null && Game1.Back2tileSheetFileName != null && Game1.Back3tileSheetFileName != null)
            {
                if (drawableLayer == 0)
                    map.FrontLayer1.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 1)
                    map.FrontLayer2.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 2)
                    map.EnemyLayer.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 3)
                    map.PlayerLayer.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 4)
                    map.ScreenLayer.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 5)
                    map.BackgroundLayer1.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 6)
                    map.BackgroundLayer2.SetTiles(selectedTileNo + 1);
                else if (drawableLayer == 7)
                    map.BackgroundLayer3.SetTiles(selectedTileNo + 1);
            }


            //Update mouse state
            curState = Mouse.GetState();

            //Update the previous keyboard state
            prevState = keyState;

            map.UpdateUserInput();

            // Update the HUD
            hud.Update();

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            //Begin the Spritbatch Call
            spriteBatch.Begin();
               
                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.FrontLayer1TileWidth,
                        -(int)drawOffset.Y * map.FrontLayer1TileHeight, FrontLayer1Width * map.FrontLayer1TileWidth, FrontLayer1Height * map.FrontLayer1TileHeight), Color.White);
     
                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.FrontLayer2TileWidth,
                        -(int)drawOffset.Y * map.FrontLayer2TileHeight, FrontLayer2Width * map.FrontLayer2TileWidth, FrontLayer2Height * map.FrontLayer2TileHeight), Color.White);

                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.FrontLayer3TileWidth,
                        -(int)drawOffset.Y * map.FrontLayer3TileHeight, FrontLayer3Width * map.FrontLayer3TileWidth, FrontLayer3Height * map.FrontLayer2TileHeight), Color.White);
          
                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.FrontLayer3TileWidth,
                        -(int)drawOffset.Y * map.FrontLayer3TileHeight, EnemyLayerWidth * map.FrontLayer3TileWidth, EnemyLayerHeight * map.FrontLayer3TileHeight), Color.White);
           
                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.PlayerTileWidth,
                        -(int)drawOffset.Y * map.PlayerTileHeight, PlayerLayerWidth * map.PlayerTileWidth, PlayerLayerHeight * map.PlayerTileHeight), Color.White);
               
                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.ScreenTileWidth,
                        -(int)drawOffset.Y * map.ScreenTileHeight, ScreenLayerWidth * map.ScreenTileWidth, ScreenLayerHeight * map.ScreenTileHeight), Color.White);

                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.Background1TileWidth,
                        -(int)drawOffset.Y * map.Background1TileHeight, BackgroundLayer1Width * map.Background1TileWidth, BackgroundLayer1Height * map.Background1TileHeight), Color.White);

                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.Background2TileWidth,
                        -(int)drawOffset.Y * map.Background3TileHeight, BackgroundLayer2Width * map.Background2TileWidth, BackgroundLayer2Height * map.Background2TileHeight), Color.White);

                    spriteBatch.Draw(pixel, new Rectangle(-(int)drawOffset.X * map.Background3TileWidth,
                        -(int)drawOffset.Y * map.Background3TileHeight, BackgroundLayer3Width * map.Background3TileWidth, BackgroundLayer3Height * map.Background3TileHeight), Color.White);


            //Draw the map
            map.DrawMap();

            //Draw the HUD
            hud.Draw();

            //Draw the selected tile overlay
            if (drawableLayer == 0)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 1)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 2)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 3)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 4)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 5)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 6)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            if (drawableLayer == 7)
            {
                if (Front1tileSheetFileName != null)
                    spriteBatch.Draw(Front1TileSheet, new Vector2(curState.X - (Front1TileWidth / 2), curState.Y - (Front1TileHeight / 2)),
                        map.tileSet[selectedTileNo], Color.White);
            }
            string layerText = "";

            if (drawableLayer == 0)
            {
                layerText = "Front Layer 1";

            }
            if (drawableLayer == 1)
            {
                layerText = "Front Layer 2";

            }
            if (drawableLayer == 2)
            {
                layerText = "Front Layer 3";
            }
            if (drawableLayer == 3)
            {
                layerText = "Enemy Layer";

            }
            if (drawableLayer == 4)
            {
                layerText = "Player Layer";

            }
            if (drawableLayer == 5)
            {
                layerText = "Screen layer";

            }
            if (drawableLayer == 6)
            {
                layerText = "Background Layer 1";

            }
            if (drawableLayer == 7)
            {
                layerText = "Background Layer 2";

            }
            if (drawableLayer == 8)
            {
                layerText = "Background Layer 3";

            }
           
            spriteBatch.DrawString(basic, layerText, new Vector2(5, 5), Color.White);

            base.Draw(gameTime);

            //End the spritebatch call
            spriteBatch.End();
        }
    }
}
